#include "EventLoop.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <iostream>
using std::endl;
using std::cout;
using std::pair;
EventLoop::EventLoop(Acceptor & acceptor)
    :_epfd(createEpollFd())
    ,_eventList(100)
    ,_islooping(false)
    ,_acceptor(acceptor)
{
    AddEpollFd(_acceptor.fd());
}

void EventLoop::loop()
{
        _islooping = true;
        //进行事件循环
        while(_islooping){
            waitEpollFd();
        }
}
void EventLoop::unloop()
{
    _islooping = false;
}
void EventLoop::waitEpollFd()
{
    
    //阻塞,vector的data函数返回的是动态数组的首元素地地址
    int nready = epoll_wait(_epfd, _eventList.data(),_eventList.size(), -1);
    cout << "after epoll_wait" << endl;
    if(nready == -1 && errno == EINTR)
    {
        return;
    }
    else if(nready == -1)
    {
        perror("epoll_wait");
        return;
    }
    else if(nready == 0)
    {
        cout << "epoll time out" << endl;
    }
    else
    {
        //遍历vector处理所有的就绪文件描述符
        for(int i = 0; i < nready; ++i)
        {
            int fd = _eventList[i].data.fd;
            cout << "58, fd = " << fd << endl;
            if(fd == _acceptor.fd())
            {
                //说明是新的连接
                handleNewConnection();
            }
            else
            {
                //说明是新的
                handleMessage(fd);
            }
        }

    }


}
int EventLoop::createEpollFd()
{
    int epfd;
    if((epfd = epoll_create1(0)) < 0)
    {
        perror("epoll_create");
    }
    cout << "createEpollFd()  _epfd = " << epfd << endl;
    return epfd;
}
void EventLoop::AddEpollFd(int fd)
{
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    event.data.fd = fd;
    event.events = EPOLLIN;
    cout << "add fd = " << fd << endl;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &event);
    if(ret < 0)
    {
        perror("epoll_ctli add");
    }
}
void EventLoop::DelEpollFd(int fd)
{
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    event.data.fd = fd;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL,fd, &event);
    if(ret < 0)
    {
        perror("epoll_ctl delete");
    }

}
void EventLoop::handleNewConnection()
{
    //accept
    int connfd = _acceptor.accept();
    if(connfd < 0)
    {
        perror("accept");
    }
    //将新的fd添加到epoll
    AddEpollFd(connfd);
    //创建新的TcpConnection对象
    TcpConnectionPtr sp(new TcpConnection(connfd));
    _conns.insert(make_pair(connfd, sp));
    sp->setAllCallbacks(_onClose, _onMessage, _onConnection);
    sp->handleConnectionCallback();

}
void EventLoop::handleMessage(int fd)
{
    //先将对应的TcpConnection找到
    auto it = _conns.find(fd);
    if(it != _conns.end())
    {
        //找到了
       if(it->second->isClosed())
       {
           it->second->handleCloseCallback();
           DelEpollFd(fd);
           _conns.erase(fd);
       }
       else
       {
            it->second->handleMessageCallback();
       }
        
    }

}
void EventLoop::setAllCallbacks(Callback &&Close, Callback &&Msg, Callback &&On)
{
    _onClose = std::move(Close);
    _onMessage = std::move(Msg);
    _onConnection = std::move(On);
}
